package com.ryder.petmatediarybackend.module.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.ryder.petmatediarybackend.common.util.RedisKeys;
import com.ryder.petmatediarybackend.common.util.RedisUtil;
import com.ryder.petmatediarybackend.module.auth.entity.SysPermission;
import com.ryder.petmatediarybackend.module.auth.entity.SysRole;
import com.ryder.petmatediarybackend.module.auth.entity.SysRolePermission;
import com.ryder.petmatediarybackend.module.auth.mapper.SysRolePermissionMapper;
import com.ryder.petmatediarybackend.module.auth.service.SysPermissionService;
import com.ryder.petmatediarybackend.module.auth.service.SysRolePermissionService;
import com.ryder.petmatediarybackend.module.auth.service.SysRoleService;
import com.ryder.petmatediarybackend.module.auth.service.SysUserRoleService;
import com.ryder.petmatediarybackend.module.auth.vo.PermissionVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 描述：角色-权限关联表(SysRolePermission)表服务实现类
 *
 * @author Ryder
 * @version 1.0
 * @since 1.0
 * 更新日期: 2025/10/26
 */
@Service("sysRolePermissionService")
@RequiredArgsConstructor
public class SysRolePermissionServiceImpl extends ServiceImpl<SysRolePermissionMapper, SysRolePermission> implements SysRolePermissionService {

    private final SysPermissionService sysPermissionService;

    private final SysRoleService sysRoleService;

    private final SysUserRoleService sysUserRoleService;

    private final RedisUtil redisUtil;

    private final Gson gson = new Gson();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignPermissions(Long roleId, List<Long> permissionIds) {
        if (permissionIds == null || permissionIds.isEmpty()) {
            return;
        }

        // 1. 查询已绑定的权限ID
        List<Long> existingPermissionIds = getPermissionIdsByRoleId(roleId);
        
        // 2. 如果已绑定的权限不为空，需要根据 code 过滤（因为权限ID是雪花ID，会变化）
        if (!existingPermissionIds.isEmpty()) {
            // 查询已绑定的权限对象
            List<SysPermission> existingPermissions = sysPermissionService.listByIds(existingPermissionIds);
            
            // 获取已绑定的权限 code 集合
            List<String> existingPermissionCodes = existingPermissions.stream()
                    .map(SysPermission::getCode)
                    .collect(Collectors.toList());
            
            // 查询待绑定的权限对象
            List<SysPermission> newPermissions = sysPermissionService.listByIds(permissionIds);
            
            // 过滤出未绑定的权限（根据 code 判断）
            permissionIds = newPermissions.stream()
                    .filter(perm -> !existingPermissionCodes.contains(perm.getCode()))
                    .map(SysPermission::getId)
                    .collect(Collectors.toList());
            
            if (permissionIds.isEmpty()) {
                // 没有新权限需要绑定
                return;
            }
        }

        // 3. 批量插入新关联（只插入未绑定的权限）
        List<SysRolePermission> list = permissionIds.stream()
                .map(permissionId -> {
                    SysRolePermission rp = new SysRolePermission();
                    rp.setRoleId(roleId);
                    rp.setPermissionId(permissionId);
                    return rp;
                })
                .collect(Collectors.toList());
        this.saveBatch(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removePermissions(Long roleId, List<Long> permissionIds) {
        if (permissionIds == null || permissionIds.isEmpty()) {
            return;
        }

        // 删除指定的权限关联
        LambdaQueryWrapper<SysRolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRolePermission::getRoleId, roleId)
                .in(SysRolePermission::getPermissionId, permissionIds);
        this.remove(wrapper);
    }

    @Override
    public List<PermissionVO> getRolePermissions(Long roleId) {
        // 1. 查询角色权限关联
        LambdaQueryWrapper<SysRolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRolePermission::getRoleId, roleId);
        List<SysRolePermission> rolePermissions = this.list(wrapper);

        if (rolePermissions.isEmpty()) {
            return List.of();
        }

        // 2. 获取权限ID列表
        List<Long> permissionIds = rolePermissions.stream()
                .map(SysRolePermission::getPermissionId)
                .collect(Collectors.toList());

        // 3. 查询权限详情
        List<SysPermission> permissions = sysPermissionService.listByIds(permissionIds);

        // 4. 转换为 VO
        return permissions.stream().map(permission -> {
            PermissionVO vo = new PermissionVO();
            BeanUtils.copyProperties(permission, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<PermissionVO> listAllPermissions() {
        // 查询所有权限
        List<SysPermission> permissions = sysPermissionService.listAllPermissions();

        // 转换为 VO
        return permissions.stream().map(permission -> {
            PermissionVO vo = new PermissionVO();
            BeanUtils.copyProperties(permission, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Long> getPermissionIdsByRoleId(Long roleId) {
        LambdaQueryWrapper<SysRolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRolePermission::getRoleId, roleId);
        return this.list(wrapper).stream()
                .map(SysRolePermission::getPermissionId)
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getUserPermissions(Long userId) {
        // 1. 先从 Redis 缓存获取
        String cacheKey = RedisKeys.buildPermissionKey(userId);
        String cacheValue = redisUtil.get(cacheKey);
        
        if (cacheValue != null) {
            return gson.fromJson(cacheValue, List.class);
        }

        // 2. 缓存不存在，查询数据库
        List<String> permissions = new ArrayList<>();
        
        // a. 获取用户角色ID列表
        List<Long> roleIds = sysUserRoleService.getRoleIdsByUserId(userId);
        
        if (roleIds.isEmpty()) {
            return permissions;
        }

        // b. 根据角色ID列表查询权限ID列表（去重）
        LambdaQueryWrapper<SysRolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysRolePermission::getRoleId, roleIds);
        List<Long> permissionIds = this.list(wrapper).stream()
                .map(SysRolePermission::getPermissionId)
                .distinct()
                .collect(Collectors.toList());

        if (permissionIds.isEmpty()) {
            return permissions;
        }

        // c. 根据权限ID列表查询权限编码列表
        List<SysPermission> permissionList = sysPermissionService.listByIds(permissionIds);
        permissions = permissionList.stream()
                .map(SysPermission::getCode)
                .collect(Collectors.toList());

        // d. 缓存到 Redis，TTL 1小时（3600秒）
        redisUtil.set(cacheKey, gson.toJson(permissions), 3600);

        return permissions;
    }

    @Override
    public List<String> getUserRoles(Long userId) {
        // 1. 先从 Redis 缓存获取
        String cacheKey = RedisKeys.buildRoleKey(userId);
        String cacheValue = redisUtil.get(cacheKey);
        
        if (cacheValue != null) {
            return gson.fromJson(cacheValue, List.class);
        }

        // 2. 缓存不存在，查询数据库
        List<String> roles = new ArrayList<>();
        
        // a. 获取用户角色ID列表
        List<Long> roleIds = sysUserRoleService.getRoleIdsByUserId(userId);
        
        if (roleIds.isEmpty()) {
            return roles;
        }

        // b. 根据角色ID列表查询角色编码列表
        List<SysRole> roleList = sysRoleService.listByIds(roleIds);
        roles = roleList.stream()
                .map(SysRole::getCode)
                .collect(Collectors.toList());

        // c. 缓存到 Redis，TTL 1小时（3600秒）
        redisUtil.set(cacheKey, gson.toJson(roles), 3600);

        return roles;
    }

    @Override
    public void refreshUserPermissionCache(Long userId) {
        String permissionCacheKey = RedisKeys.buildPermissionKey(userId);
        String roleCacheKey = RedisKeys.buildRoleKey(userId);
        redisUtil.del(permissionCacheKey);
        redisUtil.del(roleCacheKey);
    }

    @Override
    public void refreshRoleUsersPermissionCache(Long roleId) {
        // 1. 查询该角色下的所有用户ID
        List<Long> userIds = sysUserRoleService.getUserIdsByRoleId(roleId);
        
        // 2. 批量删除权限和角色缓存
        userIds.forEach(this::refreshUserPermissionCache);
    }
}
